﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Drawing;

namespace BattleThis.Core
{
	/// <summary>
	/// Represent the map of a game with all his fields.
	/// </summary>
	public class Map
	{

		#region Variablen

		#endregion

		#region Properties

		/// <summary>
		/// Gets or sets the size of the map.
		/// </summary>
		/// <value>
		/// The size.
		/// </value>
		public MapSize Size { get; set; }

		/// <summary>
		/// Gets or sets the fields of the game.
		/// </summary>
		/// <value>
		/// The fields.
		/// </value>
		public FieldDictionary Fields { get; set; }

		/// <summary>
		/// Gets or sets the name.
		/// </summary>
		/// <value>
		/// The name.
		/// </value>
		public string Name { get; protected set; }

		/// <summary>
		/// Gets or sets the max player.
		/// </summary>
		/// <value>
		/// The max player.
		/// </value>
		public int MaxPlayer { get; protected set; }

		#endregion

		#region Methoden

		/// <summary>
		/// Initializes a new instance of the <see cref="Map"/> class.
		/// </summary>
		/// <param name="size">The size of the map.</param>
		public Map( string name , MapSize size, int maxPlayer )
		{
			if( string.IsNullOrEmpty( name) )throw new ArgumentNullException( "name" );
			if( maxPlayer <= 0 ) throw new InvalidOperationException( "max Player <= 0" );

			this.Size = size;
			this.Name = name;
			this.MaxPlayer = maxPlayer;
			this.Fields = FieldDictionary.CreateInialized( this.Size );
		}

		/// <summary>
		/// Finds the specified unit on the map.
		/// </summary>
		/// <param name="unit">The unit to search.</param>
		/// <returns>Field of map where the unit is set to.</returns>
		public Field Find( Unit unit )
		{
			return Find( unit.Id );
		}

		/// <summary>
		/// Finds the specified unit-id.
		/// </summary>
		/// <param name="id">The id of a unit to find.</param>
		/// <returns>Field of map where the unit with the id is set to.</returns>
		public Field Find( int id )
		{
			//todo hulk custome Id Object.
			return ( from field in this.Fields
					 where field.Value.Unit.Id == id
					 select field ).Single().Value;
		}

		/// <summary>
		/// Gets the neighbours-positions of a specified position on the map.
		/// </summary>
		/// <param name="position">The position to find the neighbours.</param>
		/// <returns>A list of positions of the neighbours.</returns>
		public IEnumerable<Position> GetNeighbours( Position position )
		{
			if( position == null ) throw new ArgumentNullException( "position" );

			var top =  new Position( position.Column, position.Row -1 );
			var button =  new Position( position.Column, position.Row +1 );
			var leftColumn = position.Column  - 1;
			var rightColumn = position.Column + 1;
			Position[] neighbours = null;

			if( position.IsEven() )
			{
				var leftTop = new Position( leftColumn, position.Row -1 );
				var leftButtom = new Position( leftColumn, position.Row );

				var rightTop = new Position( rightColumn, position.Row -1 );
				var rightButtom = new Position( rightColumn, position.Row );

				neighbours = new Position[] { top, button, leftButtom, leftTop, rightButtom, rightTop };
			}
			else
			{
				var leftTop = new Position( leftColumn, position.Row +1 );
				var leftButtom = new Position( leftColumn, position.Row );

				var rightTop = new Position( rightColumn, position.Row +1 );
				var rightButtom = new Position( rightColumn, position.Row );

				neighbours = new Position[] { top, button, leftTop, leftButtom, rightTop, rightButtom };
			}

			return neighbours.Where( x => this.Size.IsValid( x ) );
		}

		/// <summary>
		/// Determines whether [is valid id] [the specified unit id].
		/// </summary>
		/// <param name="unitId">The unit id.</param>
		/// <returns>
		///   <c>true</c> if [is valid id] [the specified unit id]; otherwise, <c>false</c>.
		/// </returns>
		public bool IsValidId( int unitId )
		{
			return this.Fields.Any( x => x.Value.Unit.Id == unitId );
		}

        /// <summary>
        /// Removes all the unites.
        /// </summary>
        public void RemoveUnites()
        {
            foreach (var item in this.Fields)
            {
                item.Value.Unit = Unit.Empty;
            }
        }

		#endregion
	
	}
}